package wh.products;

import wh.exceptions.BadIDFormat;
import wh.exceptions.IDCollisionException;
import wh.exceptions.InvalidValueException;
import wh.iolists.StorageDiskList;

/**
 * Base/super class for the storage products
 * @author Geir
 *
 */
public class StorageDisk {
	
	private String productID;
	private String manufacturer;
	private String series;
	private String productName;
	private int capacity;
	private String busInterface;
	private int mtbf;
	private double price;
	private int inStock;
	private String subType; // I'm aware this is redundant since the 'instanceOf' keyword will be used to check sub class.
	private static final String PRODUCT_IN_ID = "pro";
	
	public StorageDisk(String productID, double price, int inStock, String subType, String manufacturer, String series,
			String productName, int capacity, String busInterface, int mtbf) throws BadIDFormat, IDCollisionException, InvalidValueException
	{
		this.productID = productID.trim();
		this.price = price;
		this.inStock = inStock;
		this.subType = subType.trim();
		this.manufacturer = manufacturer.trim();
		this.series = series.trim();
		this.productName = productName;
		this.capacity = capacity;
		this.busInterface = busInterface.trim();
		this.mtbf = mtbf;
		
		validateID();
		validateInput();
	}
	
	
	/**
     * The ID format for storage products are as follows.
     * The first three characters is "pro", as in "product", which is consistent with other ID types ("cus" and "ord").
     * Following, from index position 3 in the ID string are unique numerical values produced when new products arrive (presupposed).
     * This unique numerical value is imagined to be the primary key for the row in a table
     * where the product is stored in a relational database management system (RDBMS). The uniqueness
     * is guaranteed only for the rows in one table, therefore the IDs will be further distinguished from
     * order IDs and customer IDs by the three characters in the first positions, and six characters
     * to the end of each ID. This means that a numerical value for products can be the same as in a order ID, 
     * but they are separated chiefly by the first three characters. 
     * The important part is that the numerical values for objects inside each class hierarchies are unique.
     * 
     * The final characters in the IDs of orders and customers are different, but for products it 
     * begins with the first three letters from the manufacturer string, and ending with the abbreviated letters taken from concrete 
     * product type names: hdd or ssd. A typical ID looks like this: pro13corssd.
     * 
     * Generating unique integers in the middle of the ID can therefore be delegated to a RDBMS, and it can be from 
     * 1 to tens of thousands or more. It is assumed that for such enterprise applications that a RDBMS is used.
     * The report discusses a custom implementation of generating IDs programmatically.
     * 
     * @throws BadIDFormat
	 * @throws IDCollisionException
    */
    
	protected void validateID() throws BadIDFormat, IDCollisionException {
		
		System.out.println("About to validate StorageDisk");
		if (productID != null) 
		{
			char[] firstThreeData = { productID.charAt(0), productID.charAt(1), productID.charAt(2) };
			String proString = new String(firstThreeData);
			
			if (proString.equals(PRODUCT_IN_ID)) // This should always be "pro".
			{
				// Progressing in the validation ..
				
				int stringSize = productID.length();
				// From the size of the ID string (the end index position in it) I count back six positions to get to the
				// first character of the final six, and construct the string from there.
				char finalStartChar = productID.charAt(stringSize-6);
				char[] finalSixData = { finalStartChar, productID.charAt(stringSize-5), productID.charAt(stringSize-4), 
						productID.charAt(stringSize-3), productID.charAt(stringSize-2), productID.charAt(stringSize-1) };
				
				String endingString = new String(finalSixData);
				
				// Making sure first that stringSize-6 is not a part of the numerical part of the ID, 
				// where the final six chars should begin. I find it most likely that it is here that a digit could spill over,
				// therefore checking this one char position first.
				// Some manufacturers may have a digit in its brand name, but thats rare, and this company deals with a small 
				// amount of known/trusted manufacturers; like Intel, Corsair, Seagate and Western Digital.
				if (!Character.isDigit(finalStartChar) && !Character.isDigit(manufacturer.charAt(0))) {
					for (char c : finalSixData) // for-each is appropriate here
					{
						if (Character.isDigit(c))
							throw new BadIDFormat(productID, endingString);
					}
				}
				// So far so good, checking if the ID is unique for StorageDisks
				
				StorageDiskList.CompareProductIDs(productID); // This can throw exception
				
			}
			else
				throw new BadIDFormat(productID, proString);
			// At this point the product ID is valid.
			System.out.println("StorageDisk object valid");
		}
		else
			throw new IllegalArgumentException("It's null!");
	}
	
	/**
	 * Validates the most critical information in each object,
	 * which is productName (description), price and stock value. 
	 * 
	 * @throws InvalidValueException
	 */
	protected void validateInput() throws InvalidValueException  {
		
		if (productName != null && !(productName.length() > 4)) // productName contains the essential product info
			throw new InvalidValueException("productName", productName, "missing description");
		
		if (!(price > 0))
			throw new InvalidValueException("price", ""+price, "price not set!");
		
		if (inStock < 0)
			throw new InvalidValueException("inStock", ""+inStock, "Stock value is below zero. Some order(s) were allowed to overdraw the amount available!");
		
	}
	
	
	public void setNewInStock(int ins)
	{
		inStock -= ins;
	}
	
	/**
	 * Returns
	 * @return productID
	 */
	public String getProductID() {
		return productID;
	}
	
	public String getManufacturer() {
		return manufacturer;
	}
	
	public String getSeries() {
		return series;
	}
	
	public String getProductname() {
		return productName;
	}
	
	public int getCapacity() {
		return capacity;
	}
	
	public String getInterface() {
		return busInterface;
	}
	
	public int getMTBF() {
		return mtbf;
	}
	
	public double getPrice() {
		return price;
	}
	
	public int getInStock() {
		return inStock;
	}
	
	public String getSubType() {
		return subType;
	}

}
